/**
 * 
 *  @project Air Traff Monitor
 * 
 *  @author M.Emre ATASEVER <m.emre.atas@gmail.com>
 *  @author M.Burak ALKAN <mburakalkan@gmail.com>
 *  @author H.Burak KARAMIK <bkaramik@gmail.com>
 *
 *	`Air Traffic Monitor' is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
 
#include "kisock.h"

#include <QStringList>
#include <QSettings>


QKismetSocket::QKismetSocket() 
{
	id = 0;

	QSettings settings("qkismet", "qkismet");
	settings.beginGroup("ProtoOptions");
	alert.setOptions(settings.value("alert", QVariant(QStringList() <<"sec"<<"bssid"<< "text")).toStringList());
	net.setOptions(settings.value("network", QVariant(QStringList() << "bssid"<<"type"<<"ssid")).toStringList());
	client.setOptions(settings.value("client", QVariant(QStringList() << "bssid"<<"mac"<<"type")).toStringList());
	info.setOptions(*info.getCaps());
	card.setOptions(*card.getCaps());
	settings.endGroup();

	connect(this,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SIGNAL(stateCh(QAbstractSocket::SocketState)));
}

void QKismetSocket::Connect(QString host,int port)
{
	connectToHost(host, port);
	connect(this,SIGNAL(readyRead()),this,SLOT(Read()));
	connect(this,SIGNAL(connected()),this,SLOT(SetOptions()));
}

void QKismetSocket::Disconnect()
{
	disconnectFromHost();
}

void QKismetSocket::Read()
{
	while(canReadLine())
	{
		QByteArray line = readLine();
		int sz	= line.size();
		if(line.endsWith("\n"))
		{
			sz--;
			if(line.endsWith("\r\n"))
				sz--;
			line.truncate(sz);
		}

		if(line.startsWith("*TIME:"))
		{
			emit serverTime(line.mid(7).trimmed().toInt());
		}
		else if(line.startsWith("*NETWORK"))
		{
			networkInfo info;
			info.idx = net.getIdx();
			int i = 10;
			QVariant val;
			for(int j = line.length();i+2 < j;)
			{
				i+=	readValue(i,line,&val);
				info.props.append(val);
			}

			emit netInfo(info);
		}
		else if(line.startsWith("*ALERT"))
		{
			alertInfo info;
			info.idx = alert.getIdx();
			int i = 8;
			QVariant val;
			for(int j = line.length();i+2 < j;)
			{
				i+=	readValue(i,line,&val);
				info.props.append(val);
			}

			emit alInfo(info);
		}
		else if(line.startsWith("*CLIENT"))
		{
			clientInfo info;
			info.idx = client.getIdx();
			int i = 9;
			QVariant val;
			for(int j = line.length();i+2 < j;)
			{
				i+=	readValue(i,line,&val);
				info.props.append(val);
			}

			emit cliInfo(info);
		}
		else if(line.startsWith("*INFO"))
		{
			iInfo inf;
			inf.idx = info.getIdx();
			int i = 7;
			QVariant val;
			for(int j = line.length();i+2 < j;)
			{
				i+=	readValue(i,line,&val);
				inf.props.append(val);
			}

			emit infoInfo(inf);
		}
		else if(line.startsWith("*CARD"))
		{
			cardInfo inf;
			inf.idx = card.getIdx();
			int i = 7;
			QVariant val;
			for(int j = line.length();i+2 < j;)
			{
				i+=	readValue(i,line,&val);
				inf.props.append(val);
			}

			emit crdInfo(inf);
		}
		else if(line.startsWith("*STATUS"))
		{
			QVariant val;
			emit statInfo(line.right(line.size()-9));
		}
		else if(line.startsWith("*KISMET"))
		{
			kismetInfo info;
			QVariant val;
			int i = 9;
			i+= 	readValue(i,line,&val);
			info.version	= val.toString();


			i+= 	readValue(i,line,&val);
			info.stime  	= val.toInt();


			i+= 	readValue(i,line,&val);
			info.name	= val.toString();


			info.build	= line.mid(i+1); 

			
			emit serverInfo(info);
		}
	}
}
void QKismetSocket::SetAlertOption(QString opt, bool enable)
{
	alert.setOption(opt,enable);
	write(alert.optionsString(id++));
}
void QKismetSocket::SetNetOption(QString opt, bool enable)
{
	net.setOption(opt,enable);
	write(net.optionsString(id++));
}

void QKismetSocket::SetClientOption(QString opt, bool enable)
{
	client.setOption(opt,enable);
	write(client.optionsString(id++));
}
void QKismetSocket::SetOptions()
{
	write(alert.optionsString(id++));
	write(net.optionsString(id++));
	write(info.optionsString(id++));
	write(client.optionsString(id++));
	write(card.optionsString(id++));
	write("!");
	write(QByteArray::number(id++));
	write(" ENABLE STATUS text\r\n");
}

int QKismetSocket::readValue(int i,QByteArray data,QVariant *out)
{
	char del = 0x20;
	char b = 0;
	
	if((char)data[i] == 0x20)
	{
		b = 1;
		i++;
	}
	if((char)data[i] == 0x01)
	{	
		del = 0x01;
		i++;
		b+=2;
	}
	QByteArray val = data.mid(i,(data.indexOf(del,i))-i);
	
	out->setValue(val);
	return val.length()+b;
}

void QKismetSocket::Pause()
{
	write("!");
	write(QByteArray::number(id++));
	write(" PAUSE\r\n");
}

void QKismetSocket::Resume()
{
	write("!");
	write(QByteArray::number(id++));
	write(" RESUME\r\n");
}
void QKismetSocket::SaveSettings()
{
	QSettings settings("qkismet", "qkismet");
	settings.beginGroup("ProtoOptions");
	settings.setValue("network", *net.getSelected());
	settings.setValue("alert", *alert.getSelected());
	settings.setValue("client", *client.getSelected());
	settings.endGroup();
}


